package sender;

import common.Checksum;
import common.Packet;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
    
/**
 *
 * @author Joe
 */
public class Alternating implements PacketSender
{
    private DatagramSocket receiver;
    private Results results = new Results();
    public Alternating(DatagramSocket where)
    {
        receiver = where;
    }
    @Override
    public void send(ArrayList<Packet> packets, boolean isFiltered) 
    {
        try {
            // Iterate through all packets which are supposed to be sent
            for (int i = 0; i < packets.size(); i++)
            {
                Packet p = packets.get(i);
                try {
                    sendPacket(p, i, isFiltered);
                } catch (SocketTimeoutException e) {
                    // Try the last packet again.
                    i--;
                    results.resent++;
                }
            }
            results.message = "Packet sending successfully finished";
        }
        catch (IOException ex) {
            // Fail fast
            System.err.println("Network error: IOException");
            results.message = "Network error occurred, "
                    + "packet sending aborted.";
        }
    }    

    @Override
    public Results getResults() {
        return results;
    }
    private void sendPacket(Packet p, int i, boolean isFiltered) throws IOException, SocketTimeoutException
    {
        if (isFiltered)
        {
            // Scramble (corrupt, drop, or duplicate) the packet
            ArrayList<Packet> toSend = Filter.scramble(p, results);
            // Send the scrambled packet(s).
            for (Packet scrambled : toSend)
            {
                byte[] data = scrambled.getRaw();
                receiver.send(new DatagramPacket(data, data.length));
                results.sent++;
            }
        }
        else 
        {
            byte[] data = p.getRaw();
            receiver.send(new DatagramPacket(data, data.length));
            results.sent++;
        }
        // Wait for the response
        boolean responseReceived = false;
        do {
            byte[] data = new byte[Packet.MAX_SIZE];
            DatagramPacket dPacket = new DatagramPacket(data, data.length);
            receiver.receive(dPacket);
            Packet packet = new Packet(dPacket.getData());
            // Keep waiting if packet is corrupt or out of sequence
            responseReceived = 
                    packet.checksum == Checksum.calculate(packet) &&
                    i % 2 == packet.sequence;
        } while (!responseReceived);
    }
}


